package cn.mabach.oauth2.validateCode.imageCode;



import cn.mabach.oauth2.constant.RedisConstant;
import cn.mabach.oauth2.properties.SecurityProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;


/**
 * 校验验证码过滤器
 * OncePerRequestFilter: 所有请求之前被调用一次
 *
 */
@Component
public class ValidateCodeOnceFilter extends OncePerRequestFilter implements InitializingBean {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    private Set<String> urlSet = new HashSet<>();
    @Autowired
    private SecurityProperties securityProperties;

    private AntPathMatcher pathMatcher = new AntPathMatcher();

//    初始化实现InitializingBean的方法后 afterPropertiesSet都会被执行一次
//    判断哪些路径需要加入验证码过滤器
    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();

            String[] urls = securityProperties.getCode().getImage().getUrl().split(",");
            for (String url : urls) {
                urlSet.add(url);
            }



    }

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

        Boolean flag=false;
        for (String url : urlSet) {
            if (pathMatcher.match(url,httpServletRequest.getRequestURI())){
                flag=true;
            }
        }
        if (flag){
            try {
                validate(httpServletRequest);
            } catch (AuthenticationException e) {
//                验证失败交给失败处理器
                authenticationFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e);
                return;
            }
        }


        filterChain.doFilter(httpServletRequest,httpServletResponse);
    }


    private void validate(HttpServletRequest httpServletRequest) throws ServletRequestBindingException {
        String id = httpServletRequest.getSession().getId();
        String code = (String) stringRedisTemplate.boundHashOps(RedisConstant.KAPTCHA_KEY).get(id);

        String codeImg = ServletRequestUtils.getStringParameter(httpServletRequest, "code");


        if (StringUtils.isEmpty(code)){
            throw new ValidateCodeException("验证码已过期");
        }
        if (StringUtils.isEmpty(codeImg)){
            throw new ValidateCodeException("验证码不能为空");

        }

        if (!code.equals(codeImg)){
            throw new ValidateCodeException("验证码不正确");
        }

        stringRedisTemplate.boundHashOps(RedisConstant.KAPTCHA_KEY).delete(id);
    }
}
